home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Libraries / BlobMgr / Demo Folder / Wolf.c < prev   
Encoding:
C/C++ Source or Header  |  1994-02-21  |  5.9 KB  |  259 lines  |  [TEXT/KAHL]

  1. /*
  2.  * Blob Manager Demonstration:  Wolf & Goats module
  3.  *
  4.  * This is played on a checkerboard.  The wolf starts in one corner,
  5.  * the four goats on the opposite row.  All moves are into adjoining
  6.  * diagonal squares.  The wolf can move forward or backward, the goats
  7.  * only forward.  The goats try to trap the wolf so he can't move,
  8.  * while the wolf tries to get past the goats to the other side.
  9.  *
  10.  * This game is a variant of fox & geese.
  11.  *
  12.  * 1 August 1986        Paul DuBois
  13.  *
  14.  * 24 Dec 93
  15.  * - First two arguments to DrawBoardPos() were reversed.
  16.  * - Changed DrawBoardPos() to use RGB gray for dimmed positions when
  17.  * possible.
  18.  */
  19.  
  20. # include    "TransSkel.h"
  21.  
  22. # include    "BlobMgr.h"
  23. # include    "BlobDemo.h"
  24.  
  25.  
  26. # define    rows        8        /* number of rows on board */
  27. # define    columns        8        /* number of columns on board */
  28. # define    pieceSize    20        /* size of each piece */
  29. # define    vMessage    165        /* vertical position of message */
  30.  
  31. # define    BoardPos(b,ph,pv)    FindCheckerBoardPos(b,&board,ph,pv)
  32. # define    PosEmpty(h,v)        CheckerBoardPosEmpty(&board,h,v)
  33. # define    PosFilled(h,v)        CheckerBoardPosFilled(&board,h,v)
  34.  
  35.  
  36. static WindowPtr    wind;
  37.  
  38. static BlobSetHandle    boardBlobs = nil;
  39. static CheckerBoard        board;
  40. static BlobSetHandle    donors = nil;
  41. static BlobHandle        wolf;
  42. static BlobHandle        goat;
  43. static BlobHandle        current;
  44. static BlobSetHandle    misc;
  45. static BlobHandle        resetBlob;    /* simulated control */
  46. static short            hWolf;
  47. static short            vWolf;
  48.  
  49. static short            hMid;
  50. static Boolean            pause;
  51. static Str255            statusStr = "\p";
  52.  
  53.  
  54. static void
  55. StatusMesg (StringPtr s)
  56. {
  57. Rect    r;
  58.  
  59.     SetRect (&r, 0, vMessage, wind->portRect.right - 25, vMessage + 12);
  60.     TextBox    (s+1, (long) s[0], &r, teJustCenter);
  61.     StrCpy (statusStr, s);
  62. }
  63.  
  64.  
  65. /*
  66.  * Set the board to the initial configuration
  67.  */
  68.  
  69. static void
  70. Reset (void)
  71. {
  72. short    i;
  73.  
  74.     UnglueGlobSet (boardBlobs);        /* clear all globs */
  75.     GlueGlob (wolf, board[hWolf = 0][vWolf = 0]);
  76.     for (i = 1; i < columns; i += 2)
  77.         GlueGlob (goat, board[i][rows - 1]);
  78.     current = wolf;
  79.     StatusMesg ("\pWolf's Move");
  80.     pause = false;
  81. }
  82.  
  83.  
  84. static void
  85. WolfPause (StringPtr msg)
  86. {
  87.     StatusMesg (msg);
  88.     pause = true;
  89. }
  90.  
  91.  
  92. /*
  93.  * Test whether a piece can move or not.  The goats can only move
  94.  * forward (which for them means to a lower-numbered row), while the
  95.  * wolf can move forward or backward.
  96.  */
  97.  
  98. static Boolean
  99. CanMove (short h, short v)
  100. {
  101. BlobHandle    g;
  102.  
  103.     g = BGlob (board[h][v]);
  104.     if (g == goat && v == 0)
  105.         return (false);        /* goats can't move from row zero */
  106.     return (PosEmpty (h - 1, v - 1)
  107.             || PosEmpty (h + 1, v - 1)
  108.             || (g == wolf
  109.                 && (PosEmpty (h - 1, v + 1)
  110.                     || PosEmpty (h + 1, v + 1))));
  111. }
  112.  
  113.  
  114. static pascal void
  115. Mouse (Point pt, long t, short mods)
  116. {
  117. Str255    s;
  118. short    i;
  119.  
  120.     if (TestBlob (resetBlob, pt))
  121.     {
  122.         if (BTrackMouse (resetBlob, pt, inFullBlob))
  123.             Reset ();
  124.     }
  125.     else if (!pause)
  126.     {
  127.         BlobClick (pt, t, nil, boardBlobs);
  128.         if (BClickResult () == bcXfer)
  129.         {
  130.             if (!CanMove (hWolf, vWolf))    /* wolf locked in? */
  131.                 WolfPause ("\pGoats Win");
  132.             else if (vWolf == rows - 1)    /* wolf made it */
  133.                 WolfPause ("\pWolf Wins");
  134.             else
  135.             {
  136.                 current = (current == wolf ? goat : wolf);
  137.                 StatusMesg (current == wolf ?
  138.                                 "\pWolf's Move" : "\pGoats' Move");
  139.             }
  140.         }
  141.     }
  142. }
  143.  
  144.  
  145. /*
  146.  * When a piece is clicked on, the advisory checks whether the piece has
  147.  * any legal moves available to it.  If so, it returns true, so that
  148.  * BlobClick is allowed to drag the piece.  After the piece has been
  149.  * dragged, the advisory checks whether the position it was dragged to
  150.  * is legal, and returns true if so.
  151.  *
  152.  * Messages passed to the advisory follow the pattern
  153.  *
  154.  * { { advRClick advRClick* } advXfer* }*
  155.  *
  156.  * where * means 0 or more instances of the thing *'ed.  In particular,
  157.  * the advXfer message is never seen without a preceding advRClick.
  158.  */
  159.  
  160. static pascal Boolean
  161. Advisory (short mesg, BlobHandle b)
  162. {
  163. static short    h, v;    /* static to save board position of click on piece */
  164. short        h2, v2;
  165. Boolean        result;
  166.  
  167.     switch (mesg)
  168.     {
  169.  
  170.     case advRClick:    /* first click on piece */
  171.         if (BGlob (b) != current)
  172.             return (false);            /* can only move current piece(s) */
  173.         BoardPos (b, &h, &v);    /* find where it is */
  174.         return (CanMove (h, v));
  175.  
  176.     case advXfer:    /* Mouse released after dragging piece */
  177.  
  178.         BoardPos (b, &h2, &v2);
  179.         result = ((h2 == h - 1 && v2 == v - 1)
  180.             || (h2 == h + 1 && v2 == v - 1)
  181.             || (current == wolf
  182.                 && ((h2 == h - 1 && v2 == v + 1)
  183.                     || (h2 == h + 1 && v2 == v + 1))));
  184.         if (result == true && current == wolf)
  185.         {
  186.             hWolf = h2;        /* update wolf's position */
  187.             vWolf = v2;
  188.         }
  189.         return (result);
  190.     }
  191. }
  192.  
  193.  
  194. static pascal void
  195. Update (Boolean resized)
  196. {
  197.     DrawBlobSet (boardBlobs);
  198.     DrawBlob (resetBlob, inFullBlob);
  199.     StatusMesg (statusStr);
  200. }
  201.  
  202.  
  203. /*
  204.  * Activate the window:  Set the advisory function and set the permissions
  205.  * to transfer-only.  Clear, replace, duplication and swap are off.
  206.  * Since replace is off, the advisory doesn't have to check whether
  207.  * the dragged piece was dragged onto a blob that already has a glob.
  208.  *
  209.  * Deactivate the window:  Clear the advisory.
  210.  */
  211.  
  212. static pascal void
  213. Activate (Boolean active)
  214. {
  215.     if (active)
  216.     {
  217.         SetDragRects (wind);
  218.         SetBCPermissions (false, true, false, false, false);    /* xfer only */
  219.         SetBCAdvisory (Advisory);
  220.     }
  221.     else
  222.     {
  223.         SetBCAdvisory (nil);
  224.     }
  225. }
  226.  
  227.  
  228. void
  229. WolfInit (void)
  230. {
  231. Rect    r;
  232.  
  233.     SkelWindow (wind = GetDemoWind (wolfWindRes),
  234.                 Mouse,            /* mouse clicks */
  235.                 nil,            /* key clicks */
  236.                 Update,            /* updates */
  237.                 Activate,        /* activate/deactivate events */
  238.                 nil,            /* close window */
  239.                 DoWClobber,        /* dispose of window */
  240.                 nil,            /* idle proc */
  241.                 false);            /* irrelevant, since no idle proc */
  242.  
  243.     hMid = wind->portRect.right / 2;
  244.  
  245.     donors = MakeCheckersPieces (pieceSize);
  246.     wolf = GetBlobHandle (donors, 0);
  247.     goat = GetBlobHandle (donors, 1);
  248.     MakeCheckerBoard(&boardBlobs, &board, pieceSize);
  249.  
  250.     misc = NewBlobSet ();
  251.     SetRect (&r, 0, 0, 20, 90);
  252.     OffsetRect (&r, wind->portRect.right - 25,
  253.                     (wind->portRect.bottom - 90 - 25) / 2);
  254.     resetBlob = NewVButtonBlob (misc, &r, "\pReset", true);
  255.     Reset ();
  256.  
  257.     MakeFrontWind (wind);
  258. }
  259.